package com.ruoyi.anno;

import com.baomidou.shaun.core.context.ProfileHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class LockMethodAOP {

    @Resource
    private RedisLock redisLock;

    /**
     * 这里注意，我的注解写在同一个包下所以没有包名，如果换自己的目录，要改为@annotation(com.xxx.NotResubmit)加上完整包名.
     */
    @Around("execution(public * *(..)) && @annotation(NotResubmit)")
    public Object interceptor(ProceedingJoinPoint pjp) throws Throwable {
        // 获取到这个注解
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        NotResubmit lock = method.getAnnotation(NotResubmit.class);

        final String lockKey = generateKey(pjp);

        // 上锁
        final boolean success = redisLock.Rlock(lockKey, null, lock.delaySeconds(), TimeUnit.SECONDS);
        if (!success) {
            throw new Exception("操作太频繁!");
        }
        return pjp.proceed();
    }

    private String generateKey(ProceedingJoinPoint pjp) {
        StringBuilder sb = new StringBuilder();
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        sb.append(pjp.getTarget().getClass().getName())//类名
                .append(method.getName())
                .append(ProfileHolder.getProfile().getId());//方法名
        for (Object o : pjp.getArgs()) {
            sb.append(o.toString());
        }
        return DigestUtils.md5DigestAsHex(sb.toString().getBytes(Charset.defaultCharset()));
    }

}
